package com.yin.waimai.controller;

import com.yin.waimai.dto.DeliveryPersonDTO;
import com.yin.waimai.enums.DeliveryPersonStatus;
import com.yin.waimai.service.DeliveryPersonService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.geo.Distance;
import org.springframework.data.geo.Metrics;
import org.springframework.data.geo.Point;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 配送人员控制器
 */
@RestController
@RequestMapping("/api/v1/delivery-persons")
public class DeliveryPersonController {

    private static final Logger log = LoggerFactory.getLogger(DeliveryPersonController.class);

    private final DeliveryPersonService deliveryPersonService;

    @Autowired
    public DeliveryPersonController(DeliveryPersonService deliveryPersonService) {
        this.deliveryPersonService = deliveryPersonService;
    }

    /**
     * 创建配送人员
     */
    @PostMapping
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<DeliveryPersonDTO> createDeliveryPerson(@RequestBody DeliveryPersonDTO deliveryPersonDTO) {
        log.info("REST request to create delivery person: {}", deliveryPersonDTO.getName());
        DeliveryPersonDTO result = deliveryPersonService.createDeliveryPerson(deliveryPersonDTO);
        return ResponseEntity.status(HttpStatus.CREATED).body(result);
    }

    /**
     * 获取所有配送人员
     */
    @GetMapping
    @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
    public ResponseEntity<List<DeliveryPersonDTO>> getAllDeliveryPersons() {
        log.info("REST request to get all delivery persons");
        List<DeliveryPersonDTO> result = deliveryPersonService.findAll();
        return ResponseEntity.ok(result);
    }

    /**
     * 根据ID获取配送人员
     */
    @GetMapping("/{id}")
    @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
    public ResponseEntity<DeliveryPersonDTO> getDeliveryPerson(@PathVariable String id) {
        log.info("REST request to get delivery person: {}", id);
        return deliveryPersonService.findById(id)
                .map(ResponseEntity::ok)
                .orElse(ResponseEntity.notFound().build());
    }

    /**
     * 根据状态获取配送人员
     */
    @GetMapping("/status/{status}")
    @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
    public ResponseEntity<List<DeliveryPersonDTO>> getDeliveryPersonsByStatus(
            @PathVariable DeliveryPersonStatus status) {
        log.info("REST request to get delivery persons by status: {}", status);
        List<DeliveryPersonDTO> result = deliveryPersonService.findByStatus(status);
        return ResponseEntity.ok(result);
    }

    /**
     * 更新配送人员
     */
    @PutMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<DeliveryPersonDTO> updateDeliveryPerson(
            @PathVariable String id,
            @RequestBody DeliveryPersonDTO deliveryPersonDTO) {
        log.info("REST request to update delivery person: {}", id);
        DeliveryPersonDTO result = deliveryPersonService.updateDeliveryPerson(id, deliveryPersonDTO);
        return ResponseEntity.ok(result);
    }

    /**
     * 更新配送人员状态
     */
    @PutMapping("/{id}/status/{status}")
    @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
    public ResponseEntity<DeliveryPersonDTO> updateDeliveryPersonStatus(
            @PathVariable String id,
            @PathVariable DeliveryPersonStatus status) {
        log.info("REST request to update delivery person status: {}, {}", id, status);
        DeliveryPersonDTO result = deliveryPersonService.updateStatus(id, status);
        return ResponseEntity.ok(result);
    }

    /**
     * 更新配送人员位置
     */
    @PutMapping("/{id}/location")
    @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR', 'DELIVERY')")
    public ResponseEntity<DeliveryPersonDTO> updateDeliveryPersonLocation(
            @PathVariable String id,
            @RequestParam double longitude,
            @RequestParam double latitude) {
        log.info("REST request to update delivery person location: {}, [{}, {}]", id, longitude, latitude);
        DeliveryPersonDTO result = deliveryPersonService.updateLocation(id, longitude, latitude);
        return ResponseEntity.ok(result);
    }

    /**
     * 删除配送人员
     */
    @DeleteMapping("/{id}")
    @PreAuthorize("hasRole('ADMIN')")
    public ResponseEntity<Void> deleteDeliveryPerson(@PathVariable String id) {
        log.info("REST request to delete delivery person: {}", id);
        deliveryPersonService.deleteDeliveryPerson(id);
        return ResponseEntity.noContent().build();
    }

    /**
     * 查询附近的配送人员
     */
    @GetMapping("/nearby")
    @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
    public ResponseEntity<List<DeliveryPersonDTO>> getNearbyDeliveryPersons(
            @RequestParam double longitude,
            @RequestParam double latitude,
            @RequestParam(defaultValue = "5") double distanceKm) {
        log.info("REST request to get nearby delivery persons: [{}, {}], {}km", longitude, latitude, distanceKm);
        Point location = new Point(longitude, latitude);
        Distance distance = new Distance(distanceKm, Metrics.KILOMETERS);
        List<DeliveryPersonDTO> result = deliveryPersonService.findNearby(location, distance);
        return ResponseEntity.ok(result);
    }

    /**
     * 查询附近的空闲配送人员
     */
    @GetMapping("/nearby/idle")
    @PreAuthorize("hasAnyRole('ADMIN', 'OPERATOR')")
    public ResponseEntity<List<DeliveryPersonDTO>> getNearbyIdleDeliveryPersons(
            @RequestParam double longitude,
            @RequestParam double latitude,
            @RequestParam(defaultValue = "5") double distanceKm) {
        log.info("REST request to get nearby idle delivery persons: [{}, {}], {}km", longitude, latitude, distanceKm);
        Point location = new Point(longitude, latitude);
        Distance distance = new Distance(distanceKm, Metrics.KILOMETERS);
        List<DeliveryPersonDTO> result = deliveryPersonService.findNearbyIdle(location, distance);
        return ResponseEntity.ok(result);
    }
}